package org.springframework.beans.factory.support;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.SingletonBeanRegistry;

/**
 * @author derekyi
 * @date 2020/11/22
 */
//这个类是对单例bean操作的默认实现类（里面是对单例bean的操作），还有123级缓存,
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

	 /**
	  * 一级缓存
	  */
	private Map<String, Object> singletonObjects = new HashMap<>();

	 /**
	  * 二级缓存
	  */
	private Map<String, Object> earlySingletonObjects = new HashMap<>();

	 /**
	  * 三级缓存
	  */
	private Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>();
	//一二三级缓存其实都是一个map集合


	//这个是存有销毁方法的bean的
	private final Map<String, DisposableBean> disposableBeans = new HashMap<>();

	@Override
	public Object getSingleton(String beanName) {
		//查看你123级缓存
		Object singletonObject = singletonObjects.get(beanName);
		//刚我们存入了一份bean对象在一级缓存里，现在我们可以直接在这里获取返回了

		//1级缓存判断
		if (singletonObject == null) {
			singletonObject = earlySingletonObjects.get(beanName);
			//二级缓存判断
			if (singletonObject == null) {
				ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
				//三级缓存判断
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					//从三级缓存放进二级缓存
					earlySingletonObjects.put(beanName, singletonObject);
					singletonFactories.remove(beanName);
				}
			}
		}
		return singletonObject;
	}



	@Override
	public void addSingleton(String beanName, Object singletonObject) {
		//这个方法是添加和获取单例bean的方法
		//这里存入了一个集合，这个集合是1级缓存，我们这里重点记忆一下，我们第一个getbean的时候
		//他往一级缓存singletonObjects里又存了一份，为什么存我们不用知道
		singletonObjects.put(beanName, singletonObject); // 1

		//顺便还把23级缓存的数据删除
		earlySingletonObjects.remove(beanName); // 2
		singletonFactories.remove(beanName); // 3
	}

	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		singletonFactories.put(beanName, singletonFactory);
	}
	//这里注册，需要beanName名称，还有DisposableBean刚创建的对象
	public void registerDisposableBean(String beanName, DisposableBean bean) {
		disposableBeans.put(beanName, bean);
	}

	public void destroySingletons() {
		ArrayList<String> beanNames = new ArrayList<>(disposableBeans.keySet());
		for (String beanName : beanNames) {
			DisposableBean disposableBean = disposableBeans.remove(beanName);
			try {
				disposableBean.destroy();
			} catch (Exception e) {
				throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
			}
		}
	}
}
